﻿using System;
using System.Text;
using System.Web;
using com.huigo.Framework.ServiceUtils;
using System.Configuration;
using System.Collections.Generic;

namespace com.huigo.Framework.Passport
{
    public class UserPassport
    {
        #region 常量
        private const string HG_PASSPORT_NAME = "HG_PASSPORT_NAME_KEY";
        private const string HG_PASSPORT_USER_NAME = "HG_PASSPORT_USER_NAME_KEY";
        private const string HG_PASSPORT_USER_ID = "HG_PASSPORT_USER_ID_KEY";

        private const string COOKIE_HGNAME = "HGNAME";
        private const string COOKIE_HGUserName = "HGUserName";
        private const string COOKIE_HGUserId = "HGUID";
        private const string COOKIE_HGTOKEN = "HGULC";
        private const string COOKIE_NEW_LOGIN = "HGNEW";
        private const string COOKIE_LOGIN_OUT = "HGNEWOUT";

        private const string COOKIE_DOMAIN = "lequgo.com";
        #endregion

        #region 构造函数
        static UserPassport()
        {
        }
        #endregion

        #region 编码类型 兼容旧版本
        /// <summary>
        /// 编码类型 
        /// </summary>
        public enum EncodingType
        {
            /// <summary>
            /// GB2312编码
            /// </summary>
            GB2312 = 0,
            /// <summary>
            /// UTF8编码
            /// </summary>
            UTF8 = 1
        }
        #endregion

        #region 公共方法
        /// <summary>
        /// 从COOKIE中读取值并解密
        /// </summary>
        /// <param name="cookie"></param>
        /// <returns></returns>
        private static string[] GetCookieData(string cookie, out string md5)
        {
            md5 = null;
            if (string.IsNullOrEmpty(cookie)) return null;
            if (cookie.Length <= 8)
            {
                DeleteCookie(COOKIE_NEW_LOGIN, COOKIE_DOMAIN);
                DeleteCookie(COOKIE_LOGIN_OUT, COOKIE_DOMAIN);

                return null;
            }

            md5 = cookie.Substring(cookie.Length - 8, 8);
            cookie = cookie.Substring(0, cookie.Length - 8);

            string deCookieValue = com.loto.Common.Utils.DecodeDES(cookie);
            if (string.IsNullOrEmpty(deCookieValue)) return null;

            string[] data = deCookieValue.Split(new char[] { '+' });
            if (data.Length == 5)
                return data;
            else
                return null;
        }

        /// <summary>
        /// 创建用户信息
        /// </summary>
        /// <param name="UserName">用户名</param>
        /// <param name="loginDate">登录时间</param>
        /// <param name="expireDate">过期时间</param>
        /// <param name="userData">其它信息</param>
        /// <returns></returns>
        private static string CreateUserInfo(string UserName, long UserId, string loginDate, string expireDate, string userData)
        {
            StringBuilder builder = new StringBuilder();
            builder.Append(UserName);
            builder.Append("+");
            builder.Append(UserId);
            builder.Append("+");
            builder.Append(loginDate);
            builder.Append("+");
            builder.Append(expireDate);
            builder.Append("+");
            builder.Append(userData);

            return com.loto.Common.Utils.EncodeDES(builder.ToString());
        }

        /// <summary>
        /// 创建验证TOKEN
        /// </summary>
        /// <param name="UserName"></param>
        /// <param name="loginDate"></param>
        /// <returns></returns>
        private static string CreateToken(string UserName, string loginDate)
        {
            com.loto.Common.ASPMD5 md5 = new com.loto.Common.ASPMD5();
            return md5.MD5(UserName + loginDate).Substring(8, 8);
        }

        /// <summary>
        /// 从COOKIE中获取用户信息
        /// </summary>
        /// <returns></returns>
        private static string GetUserInfoFromCookie()
        {
            return GetCookie(COOKIE_HGUserName);
        }

        /// <summary>
        /// 从COOKIE中获取TOKEN信息
        /// </summary>
        /// <returns></returns>
        private static string GetTokenFromCookie()
        {
            return GetCookie(COOKIE_HGTOKEN);
        }

        /// <summary>
        /// 获取Cookie
        /// </summary>
        /// <param name="cookieName"></param>
        /// <returns></returns>
        private static string GetCookie(string cookieName)
        {
            HttpCookie cookie = HttpContext.Current.Request.Cookies[cookieName];
            if (cookie == null || string.IsNullOrEmpty(cookie.Value))
                return string.Empty;
            else
                return cookie.Value;
        }

        /// <summary>
        /// 设置Cookie
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="host"></param>
        /// <param name="value"></param>
        /// <param name="expire"></param>
        /// <param name="expreDate"></param>
        private static void SetCookie(string cookieName, string host, string value, bool expire, DateTime expreDate, bool httpOnly)
        {
            HttpCookie cookie = new HttpCookie(cookieName, value);
            //cookie.Domain = host;
            cookie.HttpOnly = httpOnly;
            if (expire)
                cookie.Expires = expreDate;

            HttpContext.Current.Response.AppendCookie(cookie);
        }

        /// <summary>
        /// 删除Cookie
        /// </summary>
        /// <param name="cookieName"></param>
        /// <param name="host"></param>
        private static void DeleteCookie(string cookieName, string host)
        {
            HttpCookie cookie = new HttpCookie(cookieName, "");
            //cookie.Domain = host;
            cookie.Expires = DateTime.Now.AddDays(-1);

            HttpContext.Current.Response.Cookies.Remove(cookieName);
            HttpContext.Current.Response.AppendCookie(cookie);
        }

        /// <summary>
        /// 验证票据合法性
        /// </summary>
        /// <param name="UserName"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static bool CheckToken(string UserName, string token)
        {
            if (string.IsNullOrEmpty(UserName) || string.IsNullOrEmpty(token)) return false;
            if (token.Length <= 8) return false;

            string md5 = token.Substring(token.Length - 8, 8);
            token = token.Substring(0, token.Length - 8);
            token = com.loto.Common.Utils.DecodeDES(token);

            if (string.IsNullOrEmpty(token)) return false;

            string[] data = token.Split(new char[] { '+' });
            return data.Length == 5;
        }
        #endregion

        /// <summary>
        /// 检查是否登录
        /// </summary>
        /// <param name="UserName">用户名</param>
        /// <returns>返回登录结果</returns>
        private static bool ChkIsLogin(out string uName, out string userName, out long userId)
        {
            userName = string.Empty;
            uName = string.Empty;
            userId = long.MinValue;
            string sessionName = com.loto.Common.Utils.GetSession(HG_PASSPORT_NAME);
            string sessionUserName = com.loto.Common.Utils.GetSession(HG_PASSPORT_USER_NAME);
            string sessionUserId = com.loto.Common.Utils.GetSession(HG_PASSPORT_USER_ID);
            if (sessionName != string.Empty && sessionUserName != string.Empty && !string.IsNullOrEmpty(sessionUserId))
            {
                uName = sessionName;
                userName = sessionUserName;
                userId = Convert.ToInt64(sessionUserId);
                return true;
            }

            //try
            //{
            string cookieValue = GetUserInfoFromCookie();
            string cookieToken = GetTokenFromCookie();

            if (cookieValue == string.Empty) return false;
            if (cookieToken == string.Empty) return false;

            string md5;
            string[] data = GetCookieData(cookieToken, out md5);
            if (data == null) return false;

            string tmpUserName = HttpUtility.UrlDecode(cookieValue, Encoding.GetEncoding("utf-8"));
            if (data[0].ToLower() != tmpUserName.ToLower())
            {
                return false;
            }


            userName = data[0];
            userId = Convert.ToInt64(data[1]);
            string loginDate = data[2];
            string expireDate = data[3];
            string checkToken = CreateToken(userName, loginDate);

            if (checkToken.ToLower() != md5.ToLower())
            {
                return false;
            }
            else
            {
                // 保存用户名
                com.loto.Common.Utils.StoreSession(HG_PASSPORT_USER_NAME, userName);
                com.loto.Common.Utils.StoreSession(HG_PASSPORT_USER_ID, userId.ToString());
                return true;
            }
            //}
            //catch (Exception ex)
            //{
            //    if (logger.IsErrorEnabled)
            //        logger.Error(string.Format("异常", ex));

            //    return false;
            //}
        }

        #region 登录
        /// <summary>
        /// 登录操作
        /// </summary>
        /// <param name="UserName">用户名</param>
        /// <param name="password">密码</param>
        /// <param name="days">保存时间</param>
        /// <returns>返回登录操作结果</returns>
        public static bool Login(string UserName, string password, int days)
        {
            if (days < 0) days = 0;
            string ip = com.loto.Common.Utils.GetIP();
            try
            {
                List<RequestFuncParams> argList = new List<RequestFuncParams>();
                argList.Add(new RequestFuncParams("userName", UserName));
                argList.Add(new RequestFuncParams("password", password));
                argList.Add(new RequestFuncParams("ip", ip));
                BaseService baseService = new BaseService();
                ParserXml paser = baseService.RequestEntryService(Dict.ERequestFunc.DO_USER_LOGIN, argList);
                //List<string[]> rows = paser.ReadData;

                if (paser.RowsCount > 0)
                {
                    //写入登录日志
                    List<RequestFuncParams> list = new List<RequestFuncParams>();
                    list.Add(new RequestFuncParams("type", "2"));
                    list.Add(new RequestFuncParams("custFid", paser["UserId", 0]));
                    list.Add(new RequestFuncParams("ip", ip));
                    BaseService service = new BaseService();
                    ParserXml parserXml = service.RequestEntryService(Dict.ERequestFunc.LGOIN_LOG, list);

                    List<RequestFuncParams> userlist = new List<RequestFuncParams>();
                    userlist.Add(new RequestFuncParams("userID", paser["UserId", 0]));
                    BaseService Userservice = new BaseService();
                    ParserXml rXml = Userservice.RequestEntryService(Dict.ERequestFunc.UPDATE_USER_INFO_LAST_TIME, userlist);
                    
                    DateTime now = DateTime.Now;

                    string token = CreateToken(paser["UserName"], now.ToString("yyyy-MM-dd HH:mm:ss"));

                    //session
                    com.loto.Common.Utils.StoreSession(HG_PASSPORT_NAME, paser["UserName"]);
                    com.loto.Common.Utils.StoreSession(HG_PASSPORT_USER_NAME, paser["UserName"]);
                    com.loto.Common.Utils.StoreSession(HG_PASSPORT_USER_ID, paser["UserId"]);
                    //Common.Utils.StoreSession(HG_PASSPORT_NAME, paser["UserName"]);
                    //cookies
                    string userData = CreateUserInfo(paser["UserName"], Convert.ToInt64(paser["UserId"]), now.ToString("yyyy-MM-dd HH:mm:ss"), now.AddDays(days).ToString("yyyy-MM-dd HH:mm:ss"), "");

                    bool expire = days > 0;
                    DateTime expireDate = now.AddDays(days);

                    SetCookie(COOKIE_HGNAME, COOKIE_DOMAIN, HttpUtility.UrlEncode(paser["UserName"], Encoding.GetEncoding("utf-8")), expire, expireDate, false);
                    SetCookie(COOKIE_HGUserName, COOKIE_DOMAIN, paser["UserName"], expire, expireDate, false);
                    SetCookie(COOKIE_HGUserId, COOKIE_DOMAIN, paser["UserId"].ToString(), expire, expireDate, false);
                    SetCookie(COOKIE_HGTOKEN, COOKIE_DOMAIN, userData + token, expire, expireDate, true);
                    SetCookie(COOKIE_NEW_LOGIN, COOKIE_DOMAIN, "1", expire, expireDate, false);
                    DeleteCookie(COOKIE_LOGIN_OUT, COOKIE_DOMAIN);

                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
            }

            return false;
        }

        #endregion

        #region 获取登录用户名
        /// <summary>
        /// 根据cookie输出用户名
        /// </summary>
        /// <returns>根据cookie输出用户名</returns>
        [Obsolete("推荐使用 GetCookieUserName()")]
        public static string GetCookieUserName(EncodingType encodingtype)
        {
            return GetCookieUserName();
        }

        /// <summary>
        /// 根据cookie输出用户名
        /// </summary>
        /// <returns>根据cookie输出用户名</returns>
        public static string GetCookieUserName()
        {
            string uName;
            string UserName;
            long UserId;
            ChkIsLogin(out uName, out UserName, out UserId);
            return UserName;
        }

        /// <summary>
        /// 根据cookie输出用户ID
        /// </summary>
        /// <returns>根据cookie输出用户ID</returns>
        public static long GetCookieUserId()
        {
            string uName;
            string UserName;
            long UserId = 0;
            ChkIsLogin(out uName, out UserName, out UserId);
            return UserId;
        }

        /// <summary>
        /// 根据cookie输出用户
        /// </summary>
        /// <returns>根据cookie输出用户ID</returns>
        public static string GetCookieUName()
        {
            string uName;
            string UserName;
            long UserId;
            if (ChkIsLogin(out uName, out UserName, out UserId))
                return uName;
            else
                return "aaaa";
        }

        #endregion

        #region 退出登录操作
        /// <summary>
        /// 退出登录操作
        /// </summary>
        /// <param name="encodingtype">编码</param>
        /// <returns>退出登录操作</returns>
        [Obsolete("推荐使用 LoginOut()")]
        public static bool LoginOut(EncodingType encodingtype)
        {
            return LoginOut();
        }

        /// <summary>
        /// 退出登录操作
        /// </summary>
        /// <param name="encodingtype">编码</param>
        /// <returns>退出登录操作</returns>
        public static bool LoginOut()
        {
            DeleteCookie(COOKIE_HGNAME, COOKIE_DOMAIN);
            DeleteCookie(COOKIE_HGUserName, COOKIE_DOMAIN);
            DeleteCookie(COOKIE_HGUserId, COOKIE_DOMAIN);
            DeleteCookie(COOKIE_HGTOKEN, COOKIE_DOMAIN);
            DeleteCookie(COOKIE_NEW_LOGIN, COOKIE_DOMAIN);
            SetCookie(COOKIE_LOGIN_OUT, COOKIE_DOMAIN, "1", false, DateTime.MinValue, false);
            HttpContext.Current.Session.Abandon();
            HttpContext.Current.Session.Clear();
            return true;
        }
        #endregion

        /// <summary>
        /// 检查是否登录
        /// </summary>
        /// <param name="UserName">用户名</param>
        /// <returns>返回登录结果</returns>
        public static bool ChkCookieLogin()
        {
            string uName;
            string UserName;
            long UserId;
            bool result = ChkCookieLogin(out uName, out UserName, out UserId);
            return result;
        }

        /// <summary>
        /// 检查是否登录
        /// </summary>
        /// <param name="UserName">用户名</param>
        /// <returns>返回登录结果</returns>
        private static bool ChkCookieLogin(out string uName, out string UserName, out long UserId)
        {
            UserName = string.Empty;
            uName = string.Empty;
            UserId = long.MinValue;
            //string sessionName = Common.Utils.GetSession(HG_PASSPORT_NAME);
            string sessionUserName = com.loto.Common.Utils.GetSession(HG_PASSPORT_USER_NAME);
            string sessionUserId = com.loto.Common.Utils.GetSession(HG_PASSPORT_USER_ID);
            if (sessionUserName != string.Empty && !string.IsNullOrEmpty(sessionUserId))
            {
                uName = sessionUserName;
                UserName = sessionUserName;
                UserId = Convert.ToInt64(sessionUserId);
                return true;
            }

            try
            {
                string cookieValue = GetUserInfoFromCookie();
                string cookieToken = GetTokenFromCookie();

                if (cookieValue == string.Empty) return false;
                if (cookieToken == string.Empty) return false;

                string md5;
                string[] data = GetCookieData(cookieToken, out md5);
                if (data == null) return false;

                string tmpUserName = HttpUtility.UrlDecode(cookieValue, Encoding.GetEncoding("utf-8"));
                if (data[0].ToLower() != tmpUserName.ToLower())
                {
                    return false;
                }


                UserName = data[0];
                UserId = Convert.ToInt64(data[1]);
                string loginDate = data[2];
                string expireDate = data[3];
                string checkToken = CreateToken(UserName, loginDate);

                if (checkToken.ToLower() != md5.ToLower())
                {
                    return false;
                }
                else
                {
                    // 保存用户名
                    com.loto.Common.Utils.StoreSession(HG_PASSPORT_USER_NAME, UserName);
                    com.loto.Common.Utils.StoreSession(HG_PASSPORT_USER_ID, UserId.ToString());
                    return true;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        //#region 获取权限
        //public bool IsAllowAccessed(Guid rightId)
        //{
        //    bool isAllow = false;
        //    long UserId = GetCookieUserId();
        //    if (UserId != long.MinValue)
        //    {
        //        if (BLL.UserRight.GetUserRightByUserIdRightId(UserId, rightId) != null)
        //            isAllow = true;
        //    }
        //    return isAllow;
        //}
        //#endregion

    }
}
